package com.easylinkin.linkappapi.investigation.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.bases.redis.util.RedisUtil;
import com.easylinkin.linkappapi.common.service.CommonService;
import com.easylinkin.linkappapi.common.utils.DateUtil;
import com.easylinkin.linkappapi.common.utils.message.SendMessageUtil;
import com.easylinkin.linkappapi.investigation.entity.InvestigationTask;
import com.easylinkin.linkappapi.investigation.entity.InvestigationTaskDetail;
import com.easylinkin.linkappapi.investigation.entity.InvestigationTaskModel;
import com.easylinkin.linkappapi.investigation.entity.InvestigationTaskModelContent;
import com.easylinkin.linkappapi.investigation.entity.vo.InvestigationTaskSms;
import com.easylinkin.linkappapi.investigation.mapper.InvestigationTaskMapper;
import com.easylinkin.linkappapi.investigation.service.InvestigationTaskDetailService;
import com.easylinkin.linkappapi.investigation.service.InvestigationTaskModelContentService;
import com.easylinkin.linkappapi.investigation.service.InvestigationTaskModelService;
import com.easylinkin.linkappapi.investigation.service.InvestigationTaskService;
import com.easylinkin.linkappapi.listener.InvestigationBigScreenListener;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import com.easylinkin.linkappapi.security.entity.LinkappUser;
import com.easylinkin.linkappapi.security.mapper.LinkappUserMapper;
import com.easylinkin.linkappapi.security.service.LinkappUserService;
import com.easylinkin.linkappapi.space.entity.LinkappArea;
import com.easylinkin.linkappapi.space.service.LinkappAreaService;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 排查任务 服务实现类
 * </p>
 *
 * @author TongJie
 * @since 2021-04-16
 */
@Service
public class InvestigationTaskServiceImpl extends ServiceImpl<InvestigationTaskMapper, InvestigationTask> implements InvestigationTaskService {

    @Resource
    private InvestigationTaskDetailService investigationTaskDetailService;
    @Lazy
    @Resource
    private InvestigationTaskModelService investigationTaskModelService;
    @Resource
    private LinkappUserContextProducer linkappUserContextProducer;
    @Resource
    private CommonService commonService;
    @Resource
    private LinkappUserMapper linkappUserMapper;
    @Resource
    private LinkappUserService linkappUserService;
    @Resource
    private LinkappAreaService linkappAreaService;
    @Resource
    private InvestigationTaskModelContentService investigationTaskModelContentService;
    @Resource
    private InvestigationBigScreenListener investigationBigScreenListener;
    @Resource
    private SendMessageUtil sendMessageUtil;
    @Resource
    RedisUtil redisUtil;

    /**
     * 巡检任务提醒处理
     */
    private static final String SMS_TEMPLATE_CODE_REMINDER_PROCESSING = "SMS_221055072";

    /**
     * 巡检任务提前提醒
     */
    private static final String SMS_TEMPLATE_CODE_REMINDER_ADVANCE = "SMS_221120202";


    @Override
    public InvestigationTask getInvestigationTaskWithDetailsAll(InvestigationTask investigationTask) {
        InvestigationTask investigationTaskResult = baseMapper.getInvestigationTaskWithDetails(investigationTask);
        if (investigationTaskResult == null) {
            return null;
        }
        List<InvestigationTaskDetail> details = investigationTaskResult.getInvestigationTaskDetails().stream().sorted(Comparator.comparingInt(InvestigationTaskDetail::getSortNo)).collect(Collectors.toList());
        investigationTaskResult.setInvestigationTaskDetails(details);
        QueryWrapper<InvestigationTaskModel> qw = new QueryWrapper<>();
        qw.eq("id", investigationTaskResult.getInvestigationTaskModelId());
        qw.select("execute_time", "period");
        investigationTaskResult.setInvestigationTaskModel(investigationTaskModelService.getOne(qw));
//        设置位置说明
        QueryWrapper<InvestigationTaskModelContent> qw2;
        for (InvestigationTaskDetail investigationTaskDetail : investigationTaskResult.getInvestigationTaskDetails()) {
            qw2 = new QueryWrapper();
            qw2.eq("investigation_task_model_id", investigationTaskResult.getInvestigationTaskModelId());
            qw2.eq("sort_no", investigationTaskDetail.getSortNo());
            List<InvestigationTaskModelContent> list = investigationTaskModelContentService.list(qw2);
            if (ObjectUtils.isNotEmpty(list)) {
                investigationTaskDetail.setSiteDescription(list.get(0).getDescription());
            }
        }

        return investigationTaskResult;
    }

    @Override
    public InvestigationTask getInvestigationTaskWithDetails(InvestigationTask investigationTask) {
        InvestigationTask investigationTaskResult = getInvestigationTaskWithDetailsAll(investigationTask);
        if (investigationTaskResult == null) {
            return null;
        }
//        筛选只保留所有的已处理的 以及一条未处理的
        List<InvestigationTaskDetail> details = new ArrayList<>();
        boolean haveOneUnDeal = false;
        for (InvestigationTaskDetail investigationTaskDetail : investigationTaskResult.getInvestigationTaskDetails()) {
            if (investigationTaskDetail.getDealStatus() == 1) {
                details.add(investigationTaskDetail);
            } else {
                if (!haveOneUnDeal) {
                    details.add(investigationTaskDetail);
                    haveOneUnDeal = true;
                }
            }
        }
        investigationTaskResult.setInvestigationTaskDetails(details);
        return investigationTaskResult;
    }

    @Override
    public IPage<InvestigationTask> getPage(Page page, InvestigationTask investigationTask) {
        QueryWrapper<InvestigationTask> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id", "name_", "status_", "start_time", "end_time");
        queryWrapper.eq("tenant_id", linkappUserContextProducer.getNotNullCurrent().getTenantId());
        if (ObjectUtils.isNotEmpty(investigationTask.getStatus())) {
            queryWrapper.eq("status_", investigationTask.getStatus());
        }
        if (ObjectUtils.isNotEmpty(investigationTask.getName())) {
            queryWrapper.like("name_", investigationTask.getName());
        }
        if (ObjectUtils.isNotEmpty(investigationTask.getStartTime())) {
            queryWrapper.ge("start_time", investigationTask.getStartTime());
        }
        if (ObjectUtils.isNotEmpty(investigationTask.getEndTime())) {
            queryWrapper.le("start_time", investigationTask.getEndTime());
        }
        queryWrapper.orderByDesc("modify_time", "create_time");
        return baseMapper.selectPage(page, queryWrapper);
    }

//    @Override
//    public void generateTask() {
////        查询开启的任务模板（包括模板内容）
//        InvestigationTaskModel investigationTaskModelQuery = new InvestigationTaskModel().setStatus(1);
//        List<InvestigationTaskModel> investigationTaskModels = investigationTaskModelService.getInvestigationTaskModelWithContents(investigationTaskModelQuery);
////        通过模板生成 任务实例
//        investigationTaskModels = investigationTaskModels.stream().filter(e -> ObjectUtils.isNotEmpty(e.getInvestigationTaskModelContentList())).collect(Collectors.toList());
//        Assert.notEmpty(investigationTaskModels, "查询到包含排查内容的任务设置为空");
//        generateTaskByModes(investigationTaskModels);
//
//    }

    @Override
    public void addTaskByTaskModel(InvestigationTask requestModel) {
        //   查询开启的任务模板，by id（包括模板内容）
        InvestigationTaskModel investigationTaskModelQuery = new InvestigationTaskModel().setStatus(1).setId(requestModel.getInvestigationTaskModelId());
        List<InvestigationTaskModel> investigationTaskModels = investigationTaskModelService.getInvestigationTaskModelWithContents(investigationTaskModelQuery);
        investigationTaskModels = investigationTaskModels.stream().filter(e -> ObjectUtils.isNotEmpty(e.getInvestigationTaskModelContentList())).collect(Collectors.toList());
        Assert.notEmpty(investigationTaskModels, "查询到包含排查内容的开启的任务设置为空");
//        模板内容根据顺序排序
        for (InvestigationTaskModel investigationTaskModel : investigationTaskModels) {
            List<InvestigationTaskModelContent> list = investigationTaskModel.getInvestigationTaskModelContentList();
            list = list.stream().sorted(Comparator.comparingInt(InvestigationTaskModelContent::getSortNo)).collect(Collectors.toList());
            investigationTaskModel.setInvestigationTaskModelContentList(list);
        }
        generateTaskByModes(investigationTaskModels);
    }

    private void generateTaskByModes(List<InvestigationTaskModel> investigationTaskModels) {
        //2021-04-23 chenkaixuan 修改，说明：批量增加investigationTasks，赋值修改时间
        Date createOfModifyDate = new Date();
//        根据开启的任务模板，构造要生成的具体任务列表
        List<InvestigationTask> investigationTasks = new ArrayList<>();
        for (InvestigationTaskModel investigationTaskModel : investigationTaskModels) {
            InvestigationTask investigationTask = new InvestigationTask();
            investigationTask.setName(investigationTaskModel.getName()).setTenantId(investigationTaskModel.getTenantId())
                .setCreateTime(createOfModifyDate)
                .setModifyTime(createOfModifyDate)
                .setStartTime(investigationTaskModel.getStartTime())
                .setEndTime(investigationTaskModel.getEndTime())
                .setStatus(0)
                .setInvestigationTaskModelId(investigationTaskModel.getId())
            ;
//            为后面能取到 执行时间 生成根据执行时间发送短信
            investigationTask.setInvestigationTaskModel(investigationTaskModel);
            List<InvestigationTaskDetail> investigationTaskDetails = new ArrayList<>();
            for (InvestigationTaskModelContent itmc : investigationTaskModel.getInvestigationTaskModelContentList()) {

                InvestigationTaskDetail detail = new InvestigationTaskDetail(
                    itmc.getUserId(), investigationTaskModel.getTenantId(), itmc.getInvestigationTypeName(), itmc.getSortNo(), itmc.getAreaId(), 0);

                QueryWrapper<LinkappUser> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("id", Long.parseLong(itmc.getUserId()));
                queryWrapper.select("username");
                LinkappUser user = linkappUserMapper.selectOne(queryWrapper);
                if (user != null) {
                    detail.setUserName(user.getUsername());
                }
                QueryWrapper<LinkappArea> qw = new QueryWrapper();
                qw.eq("id", itmc.getAreaId());
                qw.select("area_path");
                LinkappArea area = linkappAreaService.getOne(qw);
                if (area != null) {
                    detail.setAreaPath(area.getAreaPath());
                }
                investigationTaskDetails.add(detail);
            }
            investigationTask.setInvestigationTaskDetails(investigationTaskDetails);
            investigationTasks.add(investigationTask);
        }
//        批量插入任务列表
        insertBatch(investigationTasks);
//        生成发短信的任务
        generateSmsTask(investigationTasks);
    }

    /**
     * 生成发短信的任务，要求是任务执行时间前的半小时给第一个人发一个短信，并且执行时间到了也给第一个人发送短信
     * @param investigationTasks 巡检任务
     */
    @Async
    void generateSmsTask(List<InvestigationTask> investigationTasks) {
//        生成 key 到时间后失效，失效后事件触发生成短信
        for (InvestigationTask investigationTask : investigationTasks) {
            InvestigationTaskModel taskModel = investigationTask.getInvestigationTaskModel();
            Date executeTime = taskModel.getExecuteTime();
            Date now = new Date();
//            Date now = DateUtil.getDateFromYYYYMMDDHHmmss("2021-08-06 08:29:00");
            executeTime.setYear(now.getYear());
            executeTime.setMonth(now.getMonth());
            executeTime.setDate(now.getDate());
            long secondsSub = (executeTime.getTime()-now.getTime())/1000;
            if (secondsSub < 0) {
                continue;
            }
            InvestigationTaskSms investigationTaskSms = new InvestigationTaskSms();
            if (ObjectUtils.isEmpty(investigationTask.getInvestigationTaskDetails())) {
                continue;
            }
            InvestigationTaskDetail taskDetail0 = investigationTask.getInvestigationTaskDetails().get(0);
            if (taskDetail0.getDealStatus() == 1) {
                continue;
            }
            investigationTaskSms.setTaskName(investigationTask.getName() + "-" + taskDetail0.getInvestigationTypeName());
            investigationTaskSms.setUserName(taskDetail0.getUserName());
            investigationTaskSms.setTaskDetailId(taskDetail0.getId());
//            LinkappUser user = linkappUserContextProducer.getLinkappUserByUserName(taskDetail0.getUserName());
            LinkappUser user = linkappUserService.findByUsername(taskDetail0.getUserName());
            investigationTaskSms.setPhone(user.getPhone());
            investigationTaskSms.setStartTime(DateUtil.getYYYYMMDDHHMMSSDate(executeTime));
//            第一次提前30分钟触发
            long advanceSeconds = 30 * 60;
            if ((secondsSub - advanceSeconds) > 0) {
                String key = "1st_" + investigationTask.getId() + "_Sms_task";
                redisUtil.set(key, null, secondsSub - advanceSeconds);
                investigationTaskSms.setSmsTemplateCode(SMS_TEMPLATE_CODE_REMINDER_ADVANCE);
                redisUtil.set(key + "_param", investigationTaskSms, secondsSub - advanceSeconds + 5 * 60);
            }
            if (secondsSub > 0) {
                String key = "2nd_" + investigationTask.getId() + "_Sms_task";
                redisUtil.set(key, null, secondsSub);
                investigationTaskSms.setSmsTemplateCode(SMS_TEMPLATE_CODE_REMINDER_PROCESSING);
                redisUtil.set(key + "_param", investigationTaskSms, secondsSub + 5 * 60);
            }
        }
    }

    /**
     * 批量插入 排查任务
     *
     * @param investigationTasks vos
     */
    @Transactional(rollbackFor = Exception.class)
    public void insertBatch(List<InvestigationTask> investigationTasks) {
        //2021-04-23 chenkaixuan 修改，说明：investigationTaskDetail，赋值修改人修改时间
        for (InvestigationTask investigationTask : investigationTasks) {
            save(investigationTask);
            investigationTask.getInvestigationTaskDetails().forEach(investigationTaskDetail -> {
                investigationTaskDetail.setInvestigationTaskId(investigationTask.getId());
//                investigationTaskDetail.setCreateTime(new Date());
                investigationTaskDetail.setCreateTime(investigationTask.getCreateTime());
                investigationTaskDetail.setCreator(investigationTask.getCreator());
                investigationTaskDetail.setModifyTime(investigationTask.getModifyTime());
                investigationTaskDetail.setModifier(investigationTask.getModifier());
                investigationTaskDetail.setDealStatus(0);
            });
            investigationTaskDetailService.saveBatch(investigationTask.getInvestigationTaskDetails());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchDelete(List<Long> ids) {
        Assert.notEmpty(ids, "参数ids为空");
        QueryWrapper<InvestigationTaskDetail> qw = new QueryWrapper<>();
        qw.in("investigation_task_id", ids);
        investigationTaskDetailService.remove(qw);
        removeByIds(ids);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void handle(InvestigationTask investigationTask) {
        Assert.notNull(investigationTask, "参数 为空");
        Assert.notNull(investigationTask.getId(), "参数id 为空");
        List<InvestigationTaskDetail> details = investigationTask.getInvestigationTaskDetails();
        Assert.notEmpty(details, "参数investigationTaskDetails为空");

        for (InvestigationTaskDetail detail : details) {
            Assert.notNull(detail.getId(), "参数detail.id为空");
            commonService.setModifyInfo(detail);
            detail.setDealStatus(1);
            investigationTaskDetailService.updateById(detail);
        }
        //查询详情实例是否都完成
        //2021-04-23 chenkaixuan 修改，处理时查询是否所有详情实施都已完成，是：结束任务
        QueryWrapper<InvestigationTaskDetail> qw = new QueryWrapper<>();
        qw.eq("investigation_task_id", investigationTask.getId());
        qw.eq("deal_status", 0);
        qw.orderByAsc("sort_no");
        qw.select("id", "investigation_type_name", "user_id");
//        int count = investigationTaskDetailService.count(qw);
        List<InvestigationTaskDetail> unHandledDetails = investigationTaskDetailService.list(qw);
        if (ObjectUtils.isEmpty(unHandledDetails)) {
            investigationTask.setStatus(2);
        } else {
            investigationTask.setStatus(1);
            // 对下一个要处理的任务发短信通知  异步处理
            sendInvestigationSms(unHandledDetails.get(0), investigationTask.getName());
        }

        commonService.setModifyInfo(investigationTask);
        updateById(investigationTask);

        //发送大屏实时消息推送
        investigationBigScreenListener.sendNotice(details);
    }

    /**
     * 发送短信通知处理
     *
     * @param investigationTaskDetail 排查详情
     * @param investigationTaskName   排查任务名称
     */
    @Async
    void sendInvestigationSms(InvestigationTaskDetail investigationTaskDetail, String investigationTaskName) {
        QueryWrapper<LinkappUser> qw = new QueryWrapper<>();
        qw.eq("id", Integer.parseInt(investigationTaskDetail.getUserId()));
        qw.select("phone");
        LinkappUser linkappUser = linkappUserMapper.selectOne(qw);

        JSONObject param = new JSONObject();
        param.put("taskName", investigationTaskName + "-" + investigationTaskDetail.getInvestigationTypeName());
        // 发送短信
        sendMessageUtil.sendSms(linkappUser.getPhone(), SMS_TEMPLATE_CODE_REMINDER_PROCESSING, param.toString());
    }

    /***
     * 查询 大屏隐患排查统计
     * @return
     */
    @Override
    public Map<String,Long>  getInvestigationBigScreenCount(){
        InvestigationTask investigationTask=new InvestigationTask();
        investigationTask.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        return baseMapper.getInvestigationBigScreenCount(investigationTask);
    }

    @Override
    public void sendInvestigationSms(String key) {
        InvestigationTaskSms investigationTaskSms = (InvestigationTaskSms) redisUtil.get(key);
        if (investigationTaskSms != null) {
            JSONObject param = new JSONObject();
            param.put("taskName", investigationTaskSms.getTaskName());
            param.put("startTime", investigationTaskSms.getStartTime());
            Long detailId = investigationTaskSms.getTaskDetailId();
            QueryWrapper<InvestigationTaskDetail> qw = new QueryWrapper<>();
            qw.eq("id", detailId);
            qw.select("deal_status");
            InvestigationTaskDetail investigationTaskDetail = investigationTaskDetailService.getOne(qw);
            if (investigationTaskDetail != null && investigationTaskDetail.getDealStatus().equals(0)) {
                // 发送短信
                sendMessageUtil.sendSms(investigationTaskSms.getPhone(), investigationTaskSms.getSmsTemplateCode(), param.toString());
            }
        }
        redisUtil.del(key);
    }
}
